
/*
	本汇编文件主要处理那些底层硬件错误
	页错误异常在mm中处理
	该文件页处理 fpu 异常（没有测试过）
 */
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved
.globl _alignment_check

_divide_error:
	pushl $do_divide_error
no_error_code:
    /* 
     * 交换%eax寄存器内容和 %esp 指向的地址的内容，实际就是
     * eax 中存放的是 待真实执行的中断处理子函数，例如 do_divide_error
     * 而把 %eax 当前寄存器的内容放入到 当前 esp 指向的地方
     */
	xchgl %eax,(%esp)       # 因此可以看到在出栈的时候，最后一个pop直接到 %eax
	pushl %ebx
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	pushl %ebp
	push %ds
	push %es
	push %fs
	pushl $0		# "error code" 错误码默认是0
	lea 44(%esp),%edx       # 中断刚进入时候的 %esp 地址
	pushl %edx 
	movl $0x10,%edx         # 这里又重新加载了一遍段寄存器
	mov %dx,%ds
	mov %dx,%es
	mov %dx,%fs
	call *%eax      # 调用实际中断子程序进行处理
	addl $8,%esp
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax
	iret

_debug:
	pushl $do_int3		# _do_debug
	jmp no_error_code

_nmi:
	pushl $do_nmi
	jmp no_error_code

_int3:
	pushl $do_int3
	jmp no_error_code

_overflow:
	pushl $do_overflow
	jmp no_error_code

_bounds:
	pushl $do_bounds
	jmp no_error_code

_invalid_op:
	pushl $do_invalid_op
	jmp no_error_code

_coprocessor_segment_overrun:
	pushl $do_coprocessor_segment_overrun
	jmp no_error_code

_reserved:
	pushl $do_reserved
	jmp no_error_code

/*
_irq13:
	pushl %eax
	xorb %al,%al
	outb %al,$0xF0
	movb $0x20,%al
	outb %al,$0x20
	jmp 1f
1:	jmp 1f
1:	outb %al,$0xA0
	popl %eax
	jmp coprocessor_error
*/

_double_fault:
	pushl $do_double_fault
error_code:
	/*
	 * 这种先把想要放入寄存器的参数压栈
	 * 然后通过与先要压栈的寄存器交换，达到了两个效果
	 * 参数被交换到对应的寄存器，对应的寄存器又被压栈
	 * 在需要传递参数的时候，是一个小技巧
	 */
	xchgl %eax,4(%esp)		# error code <-> %eax
	xchgl %ebx,(%esp)		# &function <-> %ebx
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	pushl %ebp
	push %ds
	push %es
	push %fs
	pushl %eax			# error code
	lea 44(%esp),%eax		# offset
	pushl %eax
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	call *%ebx
	addl $8,%esp # 这里跳过了 111 行和 113行
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax # %eax --- 实际是 $do_double_fault
	iret

_invalid_TSS:
	pushl $do_invalid_TSS
	jmp error_code

_segment_not_present:
	pushl $do_segment_not_present
	jmp error_code

_stack_segment:
	pushl $do_stack_segment
	jmp error_code

_general_protection:
	pushl $do_general_protection
	jmp error_code

_alignment_check:
	pushl $do_alignment_check
	jmp error_code